11 - Input Devices
Sensing a Magnetic Field with a Hall Sensor
This week was one of the few were I already knew what I would like to exactly do before the week started. As this topic is actually the last week with electronics, I already previously designed and manufactured a board for my final project that should be capable of reading the output of a Hall sensor. For this, I already had to pick a certain sensor, which I will connect to the board this week. This weeks's assignment were:
- Group Assignment
- Probe an input device's analog levels and digital signals
- Individual Assignment
- Measure something: Add a sensor to a microcontroller board that you have designed and read it
Group Assignment
For the group assignment, we had to probe an output of an input device. This should be done for one digital and one analog output. In this case, we did this only for one sensor module that supplies the user with an analog and a digital output, namely the same hall sensor, that I have been using for my individual assignment (see below).
In principle, we connected the break out board to a power supply via the power and ground pins of a microcontroller. Additionally, the digital as well as analog output of the module were joined with a digital and analog channel of an oscilloscope. With the latter the digital and analog outputs were measured while approaching and withdrawing the sensor with a magnet. Here, the analog output of the sensor was a true analog value which is depending on the pole of the magnet and its distance in all spatial directions. The sensitivity and by this the reaction of the sensor to the magnet can be increased and decreased by turning a potentiometer on the sensor's break out board.
The output of the digital pin was quite surprising as it actually is something like a PWM signal just not with a rectangular wave patter but rather a sawtooth pattern with curved edges. Have a look at the image to see the output.
The amplitude of the digital signal is about 3.9 V with a duty cycle of about 70.1% for a continuous pattern.
For the details on the group assignment, please refer to our group page. You can find it here.
Individual Assignment
This week's task were simple for me as I already made a big effort in the electronics design. Here, I designed a PCB for my final project according to the external components I needed. However, to do this, I firstly researched and identified which components are the best to use with regards to availability. Hence, for this week, I already had a board and a sensor, that I wanted to connect.
The board, I was using for this assignment is the one I made in the electronics design week. As a sensor, I used a Hall sensor that should be able to measure the strength of a magnetic field qualitatively. For my final project, the magnetic field is generated by a diametrical magnet that is mounted to the rotating shaft. By measuring the field strength, the angle of the rotation should be sensed.
However, to measure something with this sensor, I firstly had to establish a serial communication between the board and my computer, then take some preliminary measurements and lastly actually measure the strength of the magnetic field qualitatively.
Establishing a Serial Communication
To allow for measuring something with the Hall sensor and actually display the readings, I need an output device, preferably a display that can show the readings. However, instead of connecting such a component directly to the board, I decided to let the board send the readings to the serial monitor of the Arduino IDE such that my computer can display the readings.
In order to establish a serial communication via UART, I firstly researched on how to program that with the Arduino IDE. Here, I specifically searched for a sketch that also allows me to specify the Rx and Tx pins as I did not know whether the they are already pre-configured. Here, I found this documentation where they used the SoftwareSerial library.
I copied the code from that website into a new Arduino sketch. Then, I only added a delay to send the message "100" every half of a second abd few lines to make an LED flash whenever a serial message is send. The pin definitions were set in accordance to the pinout that Arduino uses for referencing it as shown here. Next, I setup the Arduino IDE and connected the board to my computer via a programmer board and the UPDI pins as shown here. Lastly, I uploaded the Arduino sketch to the microcontroller. The code is shown below.
#include "SoftwareSerial.h"
// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;
// Declare and initialize led pin
const int led_pin = 9;
// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);
void setup(){
// Set the pin modes of UART pins
pinMode(rx_pin, INPUT); // Receiving requires input
pinMode(tx_pin, OUTPUT); // Transmitting requires output
// Set led as output
pinMode(led_pin, OUTPUT);
// Start the serial communication at 9600 bits/sec
mySerial.begin(9600);
}
void loop(){
mySerial.println("100"); // Send the message "100"
// Flash the LED
digitalWrite(led_pin,HIGH);
delay(100);
digitalWrite(led_pin,LOW);
// Wait some time (500ms in total)
delay(400);
}
As I saw the built-in LED flashing, I continued with establishing a physical serial connection. Here, I firstly removed all connections from the board including the programmer board and secondly connected an FTDI module to the FTDI pins of the board. Then, I connected the FTDI module to my computer with a USB cable. This setup is shown in the following picture.
As soon as I had connected the FTDI module to my computer, the power LED turned on. Slightly later, the blue built-in LED on the board started to flash indicating whenever a serial message was sent.
Next, I wanted to open the serial monitor of the Arduino IDE by going to Tools > Serial Monitor. However, this gave me an error message that the board at the chosen COM is not available. Therefore, I changed the port to another one that appeared only after connecting the board to my computer via the FTDI module. This now allowed me to open the serial monitor. Lastly, I specified the baud rate to the 9600 bits per second that I defined in the sketch for serial communication.
As you can see in the video below, this communication worked flawless. The LED flashed every time a serial message was received.
Serial Communication with the Microcontroller Receiving "100" every Half Second on My Computer
Preliminary Measurements with a Hall Sensor
After having established a serial communication with the board, I wanted to achieve that the message
consists of a reading of the sensor. For this, I slightly modified the code by adding a variable for the
pin of the hall sensor and modifying the pin mode. Just before a serial message is sent, the analog
value of the pin is measured and stored in the variable val
which is then sent via the
serial communication.
Next, I connected the board to my computer via the programmer board and UPDI connections again and set the port to the right COM. Then, I uploaded the modified sketch shown below.
#include "SoftwareSerial.h"
// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;
// Declare and initialize led and hall sensor pin
const int led_pin = 9;
const int hall_pin = 8;
// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);
void setup(){
// Set the pin modes of UART pins
pinMode(rx_pin, INPUT); // Receiving requires input
pinMode(tx_pin, OUTPUT); // Transmitting requires output
// Set led as output
pinMode(led_pin, OUTPUT);
// Set sensor as input
pinMode(hall_pin, INPUT);
// Start the serial communication at 9600 bits/sec
mySerial.begin(9600);
}
void loop(){
// Read the analog value of the pin and send it via serial communication
int val = analogRead(hall_pin);
mySerial.println(val);
// Flash the LED
digitalWrite(led_pin,HIGH);
delay(100);
digitalWrite(led_pin,LOW);
// Wait some time (500ms in total)
delay(400);
}
After the upload, I disconnected the programmer board and connected the FTDI module to my computer. Next, I attached the Hall sensor to my board. For this, three cables are needed, one for VCC and the ground respectively and the last one for the data. This sensor offers two data connections. One of them is a digital output signal that switches between a high an low voltage level and by this senses whether there is a magnet close by or not. The other output signal is analog which also allows to estimate the magnetic field strength. Here, I chose the latter as this also allows to sense the orientation of a magnet as needed for my final project.
In the Arduino IDE, I again changed the port and opened the serial plotter via Tools > Serial Plotter. Then, I used a magnet that I found on a whiteboard and approached the hall sensor with one flat side and consecutively with the opposite side as shown in the video below.
Moving the Magnet
As shown in the image below from the serial plotter, the baseline of the sensor without any magnet close to it, the sensor's reading is at about 550. When one side of the magnet approaches the sensor, the measurements increase drastically. Vice versa, if the other side of the magnet, i.e. the opposite polarization, approaches the sensor, the measurements decrease, however to not such a big extent as the peak. This might be due to the cap on the magnet, that prevents me to approach the magnet as closely as with the other side.
Measuring the Strength of an Magnetic Field Qualitatively
After I successfully tested the sketch and the circuit's connection, I continued with a more sophisticated program. Here, I aimed for a higher time-wise resolution. Therefore, I deleted everything regarding the LED and decreased the pause in the end of the loop.
To upload the modified sketch as shown below, I again connected the board via a programmer board and UPDI pins. Then, I selected the right port in the Arduino IDE and uploaded the program.
#include "SoftwareSerial.h"
// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;
// Declare and initialize hall sensor pin
const int hall_pin = 8;
// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);
void setup(){
// Set the pin modes of UART pins
pinMode(rx_pin, INPUT); // Receiving requires input
pinMode(tx_pin, OUTPUT); // Transmitting requires output
// Set sensor as input
pinMode(hall_pin, INPUT);
// Start the serial communication at 9600 bits/sec
mySerial.begin(9600);
}
void loop(){
// Read the analog value of the pin and send it via serial communication
int val = analogRead(hall_pin);
mySerial.println(val);
// Add a small pause of 50ms
delay(50);
}
Once the upload was complete, I disconnected the programmer board, connected the FTDI module to the PCB and my computer and selected the right port in the Arduino IDE. Lastly, I opened the serial plotter again and repeated moving the magnet to the sensor, first facing the one side and consecutively the other side.
As you can see in the image of the plotter below, many more measurements were taken while the magnet was moved in approximately the same speed. This also allows to see more details on the exact movement.
Angle Measurements with a Hall Sensor
With the setup above, I investigated the functional principles of the sensor. In the future, for my final project, I would like to use this sensor for angle measurements. Here, the magnet should be mounted to a rotating shaft and by this rotate according to the shaft. The sensor should then measure the magnetic field strength. With this, angle measurements should be possible.
To make this possible, the magnet must be oriented such that a rotation should induce a change of the magnetic field strength. Here, the easiest would be to use a diametric magnet, where each pole consist of an extruded semicircle as shown in the image.
To finish this part with appropriate angle measurements, I bought diametric magnets. Next, I had to design and manufacture a magnet holder to hold the magnet at the end of the shaft. With this, I was then able to record the angle of a shaft that is continuously rotated by the motor.
Design and Manufacturing of the Magnet Holder
The magnet holder was designed in Fusion 360. I started by drawing a ring on the XY plane with an inner diameter of 10 mm, i.e. the outer diameter of the diametric magnet as well as the shaft, plus a tolerance of 0.4 mm. The thickness of the ring was set to be 2.5 mm. I extruded it by 23 mm and closed one of the ends with a 10 mm extrusion. Next, I drew another ring on the open end of the structure with the same inner diameter and a wall thickness of 10 mm. This ring was extruded by another 10 mm generating the raw structure of the magnet holder.
Next, to keep the magnet holder and the magnet itself attached to the shaft, I made rectangular inserts for nuts and orthogonally to it circular inserts for the according bolts. The bolts can be used as set screws to tighten the 3D printed part against the shaft and the magnet.
Lastly, I added a chamfer to between the two rings of the raw structure to make a smoother finish.
From Fusion, this design was exported as an .stl file which was imported into the software Ultimaker Cura. Here, the machine code for an Ultimaker S5 was generated using the profile "Normal - 0.15 mm" without any supports and black Ultimaker PLA as a material. The generated file was brought to the 3D printer via a flash drive where it was started by selecting the file and confirming the start.
Programming Motor Rotations and Angle Measurements
Next, I programmed the board with the setup shown above. The code that I uploaded to the board is basically the same as in the previous section but also performs a motor step right before reading the analog value of the hall sensor and sending the reading to my computer via the serial communication. However, the sensor readings are averaged over ten measurements.
#include "SoftwareSerial.h"
// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;
// Declare and initialize hall sensor pin
const int hall_pin = 8;
// Define pin numbers for motor driver
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable
// set number of steps that the motor should rotate
const int steps = 16*200*2;
int sum = 0;
// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);
void setup() {
// Set the pin modes of UART pins
pinMode(rx_pin, INPUT); // Receiving requires input
pinMode(tx_pin, OUTPUT); // Transmitting requires output
// Set sensor as input
pinMode(hall_pin, INPUT);
// Start the serial communication at 9600 bits/sec
mySerial.begin(9600);
// Define all pins for motor driver as output
pinMode(stepPin,OUTPUT);
pinMode(dirPin,OUTPUT);
pinMode(enaPin,OUTPUT);
// Enable the motor driver
digitalWrite(enaPin,LOW);
digitalWrite(dirPin,HIGH); // Set the rotation to one particular direction
}
void loop() {
// Perform a certain number of steps
for(int x = 0; x < steps; x++) {
// Generate a pulse
digitalWrite(stepPin,HIGH);
delayMicroseconds(700);
digitalWrite(stepPin,LOW);
delayMicroseconds(700);
// Read the analog value of the pin and send it via serial communication
int val = analogRead(hall_pin);
// Average the readings over ten points
if (x%10 == 0){
mySerial.println(sum/10);
sum = 0;
}
else {
sum = sum + val;
}
}
}
Setup for Angle Measurements
The setup to measure the angle that is generated by a continuous rotation of a motor consist also of the serial connection (see above). Additionally, the Hall sensor is connected to it (see above). In addition however, the stepper motor and a bench power supply is connected as shown in the assignment on output devices. Lastly, I attached the magnet holder with a magnet to the motor shaft. A photo of the complete setup including the programmer board is shown below.
During the measurements, I tried to hold my hand as steady as possible to keep a constant distant to the magnet.
Results of Angle Measurements
Once everything was setup, I set the bench power supply to 24 V and a load-dependent current. As soon as the power was supplied to the motor, it started rotating as shown in the video.
Motor Rotating During the Angle Measurements
In addition, I opened the serial plotter via Tools > Serial Plotter which showed the sensor readings below. The deviations of the slope in the readings correspond to an off-centric rotation of the magnet as the magnet holder is designed for a 10 mm shaft.
Source Code for Download
- UART Communication (.ino): Arduino sketch to establish a UART communication with specified pins
- Preliminary Measurement (.ino): Arduino sketch for preliminary measure the magnetic field strength with a hall sensor
- Measuring Magnetic Field Strength (.ino): Arduino sketch to measure the magnetic field strength qualitatively with a higher time-wise resolution
- Measuring Angle of Motor Rotation (.ino): Arduino sketch to measure the angle qualitatively that is generated by a continuous motor rotation